package signGrammar.controller;

import java.util.Map;

import javax.swing.JOptionPane;

import signGrammar.expressions.IGrammarExpression;
import signGrammar.expressions.packages.IExpressionPackage;
import signGrammar.expressions.util.EExpressionElementClass;
import signGrammar.view.CViewAboutContent;
import signGrammar.view.CViewMainFrame;
import signGrammar.view.CViewMainFrame.IMainFrameListener;
import signGrammar.view.CViewNonterminalButton.INonterminalListener;
import signGrammar.view.CViewNonterminalChoiceButton.INonterminalChoiceListener;

public class CControllerMainFrame {
	
	private final CViewMainFrame mainFrame;
	private final CMainFrameListener mainFrameListener;
	private final CNonterminalListener nonterminalListener;
	private final CNonterminalChoiceListener nonterminalChoiseListener;
	private final CExpressionConverter converter;
	private final Map<String, IExpressionPackage> packages;
	
	private IExpressionPackage expressionPackage;
	
	public CControllerMainFrame( CViewMainFrame frame, Map<String, IExpressionPackage> pgs){
		nonterminalChoiseListener = new CNonterminalChoiceListener();
		nonterminalListener = new CNonterminalListener();
		mainFrameListener   = new CMainFrameListener();
		converter           = new CExpressionConverter();

		mainFrame = frame;
		mainFrame.addListener(mainFrameListener);
		packages  = pgs;
		
		reload(packages.keySet().iterator().next()); // it's important -> reload should be here
		mainFrame.setPackagesChoises( packages.keySet().toArray( new String[ packages.keySet().size() ] ) );
	}
	
	public CControllerMainFrame startApp(){
		mainFrame.startUI(); 
		return this;
	}
	
	private IGrammarExpression grammarExpression;
	private void reload(String packageName){
		expressionPackage = packages.get(packageName);
		clear();
		mainFrame.setProductions( converter.convertToProductions( expressionPackage.getProductionsMap() ) );
	}
	private void clear(){
		grammarExpression = expressionPackage.reload().getStartingExpression();
		mainFrame.setPrimitives( expressionPackage.getEvaluator().getPrimitives() );
		mainFrame.setDeductionContent(
			converter.convertToDeduction(grammarExpression, nonterminalListener)
		);
	}

	private final CViewAboutContent aboutContent = new CViewAboutContent();
	private class CMainFrameListener implements IMainFrameListener{
		@Override public void aboutClicked() {
			JOptionPane.showMessageDialog(
				mainFrame,
				aboutContent,
				"About",
				JOptionPane.INFORMATION_MESSAGE);
		}
	
		@Override public void clearClicked() {
			mainFrame.clearDrawingPane();
			mainFrame.clearDeductionContent();
			mainFrame.clearOptionContent();
			clear();
		}
	
		@Override public void drawClicked() {
			try{
				mainFrame.drawShape(
					grammarExpression.evaluate( expressionPackage.getEvaluator() )
				);
			}catch(Exception e){
				mainFrame.setDrawClearButtonState("Draw");
				JOptionPane.showMessageDialog(
						mainFrame,
						"You can draw rigth now!\n" +
						"The deduction has to be done.",
						"Error",
						JOptionPane.ERROR_MESSAGE);
			}
		}
		@Override public void packageChoosed(String packageName){
			reload(packageName);
		}
	}
	
	private class CNonterminalListener implements INonterminalListener{
		@Override public void nonterminalClicked(String nameID) {
			mainFrame.setOptionsContent(
				converter.convertToChoises(
					nameID,
					expressionPackage.getProductionsMap().get( EExpressionElementClass.parseVarType(nameID) ),
					nonterminalChoiseListener
				)
			);
		}
	}
	
	private class CNonterminalChoiceListener implements INonterminalChoiceListener {
		@Override public void nonterminalChoise(String nameID, IGrammarExpression expression) {
			grammarExpression = grammarExpression.replace( nameID, expression );
			mainFrame.setDeductionContent(
				converter.convertToDeduction(grammarExpression, nonterminalListener)
			);
			mainFrame.clearOptionContent();
		}
	}
}
 